package com.liuzhilong.infrastructure.framework.netty.api.standard.codec;

import com.liuzhilong.infrastructure.framework.netty.api.standard.command.Command;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ReplayingDecoder;

import java.util.List;

/**
 * Command的解析器<br>
 * 使用{@link ReplayingDecoder} 进行解析
 */
public class CommandDecoder extends ReplayingDecoder<CommandDecoder.State> {
    //初始化一个新的decoder的时候，设置解析从magic开始
    public CommandDecoder(){
        super(State.MAGIC);
    }
    
    private CommandCodec commandCodec = new CommandCodec();

    /**
     * 解析数据流到command信息
     * @param ctx 上下文
     * @param in
     * @param out
     */
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
        switch (state()){
            case MAGIC:
                byte magic = in.readByte();
                if(!CommandCodec.checkMagic(magic)){
                    throw new IllegalArgumentException("illegal packet [magic]" + magic);
                }
                checkpoint(State.TYPE);
            case TYPE:
                commandCodec.setType(in.readByte());
                checkpoint(State.BODY_LENGTH);
            case BODY_LENGTH:
                commandCodec.setBodyLength(in.readInt());
                checkpoint(State.BODY);
            case BODY:
                byte[] body = new byte[commandCodec.getBodyLength()];
                in.readBytes(body);
                out.add(commandCodec.finallyToCommand(body));
                //重新设置为校验模数状态
                checkpoint(State.MAGIC);
        }
    }

    /**
     * 定义解析的步骤阶段
     * @author longandai
     */
    public enum State{
        //校验魔数
        MAGIC,
        //获取type
        TYPE,
        //获取body长度
        BODY_LENGTH,
        //获取body信息
        BODY
    }
}
